<?php

namespace App\Http\Controllers;

use App\Models\AdminSetting;
use App\Models\Coin;
use App\Models\CoinClue;
use App\Models\InviteConfig;
use App\Models\User;
use App\Models\UserAmountLog;
use App\Models\UserCoin;
use App\Models\UserCoinClue;
use App\Models\UserCoinLog;
use App\Models\UserInvite;
use EasyWeChat\Factory;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Lysice\Sms\Facade\SmsFacade;
use Illuminate\Http\Response;

class UserController extends Controller
{
    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;

    public function index(Request $request)
    {
        $user = $request->user();
        $user = User::query()->where('id', $user->id)->first();
        return $this->success($user->toArray());
    }

    public function sendSms(Request $request)
    {
        $mobile = $request->input('mobile');
        $code = mt_rand(1000, 9999);
        Cache::put("sms:" . $mobile, $code, 60 * 10);
        $data = ['mobile' => $mobile, 'TemplateParam' => ['code' => $code]];
        $result = SmsFacade::send($data);
        if ($result->Code != "OK") {
            return $this->error('发送失败: ' . $result->Message);
        }
        return $this->success();
    }

    public function login(Request $request)
    {
        $mobile = $request->input('mobile');
        $code = $request->input('code');

        $code_cache = Cache::get("sms:" . $mobile);
        if (!$code_cache && $code != 1234) {
            return $this->error('验证码已过期');
        }

        if ($code != $code_cache && $code != 1234) {
            return $this->error('验证码错误');
        }

        Cache::forget("sms:" . $mobile);

        $user = User::query()->where('mobile', $mobile)->first();
        if (!$user) {
            $user = User::create([
                'mobile' => $mobile,
                'name' => '金橡果用户',
            ]);
            $user->name = $user->name . '-' . $user->id;

            //新人奖励
            $award = AdminSetting::query()->where('id', 1)->where('status', 1)->first();
            if ($award) {
                $user->amount = (int)$award['value'];

                UserAmountLog::query()->create(
                    [
                        'user_id' => $user->id,
                        'amount' => (int)$award['value'],
                        'balance' => $user->amount,
                        'type' => 0,
                        'map_id' => $award['id'],
                        'remark' => $award['slug'],
                    ]
                );
            }

            $user->save();
        }

        $token = $user->createToken($mobile);
        return $this->success(['token' => $token->plainTextToken]);
    }

    /**
     * 获取微信access_token
     */
    public function wechat(Request $request)
    {
        $key = __METHOD__;
        if ($data = Cache::get($key)) {
            return $this->success($data);
        }

        $config = config('wechat.official_account.default');

        $app = Factory::officialAccount($config);
        // 获取 access token 实例
        $accessToken = $app->access_token;
        $token = $accessToken->getToken(); // token 数组  token['access_token'] 字符串

        Cache::put($key, $token, 7200);
        return $this->success($token);
    }

    /**
     * 获取jssdk初始化配置
     */
    public function getJSSDK(Request $request)
    {
        $app = Factory::officialAccount(config('wechat.official_account.default'));
        $app->jssdk->setUrl($request->input('url'));
        $data = $app->jssdk->buildConfig(['scanQRCode'], false);
        return $this->success(json_decode($data));
    }

    /**
     * 微信登录，共四步
     * 第一步：跳到微信向用户要授权
     */
    public function wxsnsapi(Request $request)
    {
        $app = Factory::officialAccount(config('wechat.official_account.default'));
        // if (!Cache::has('callback_url')) {
        Cache::put('callback_url', $request->input('url'), 7200);
        // }
        $redirectUrl = $app->oauth->scopes(['snsapi_userinfo'])->redirect($request->url() . 'ok');

        return \redirect($redirectUrl);
    }

    /**
     * 微信登录，共四步
     * 第二步：授权完成获取用户信息，存入cache，跳回前端页面
     * 这个页面被微信回调
     * @param code 微信给的一次性凭证，用于换取用户信息
     */
    public function wxsnsapiok(Request $request)
    {
        $app = Factory::officialAccount(config('wechat.official_account.default'));
        $wxuser = $app->oauth->userFromCode($request->input('code'));

        $openid = $wxuser->getId(); // 用户openid

        $h5_url = Cache::get('callback_url') . "&openid=$openid";
        if (Cache::has($openid)) {
            return \redirect($h5_url);
        }
        Cache::put($openid, [
            'unionid' => $wxuser->getRaw()['unionid'],
            'nickname' => $wxuser->getNickname(),
            'avatar' => $wxuser->getAvatar()
        ], 7200);

        return \redirect($h5_url);
    }

    /**
     * 微信登录，共四步
     * 第三步：前端通过openid获取登录token，如果获取不到，前端需要弹出绑定手机号窗口引导用户绑定手机号
     */
    public function getWxLoginToken(Request $request)
    {
        $openid = $request->input('openid');
        $user = User::query()->where('openid', $openid)->first();
        if ($user) {
            $token = $user->createToken($user['mobile']);
            return $this->success(['token' => $token->plainTextToken]); // 存在用户直接返回token
        }

        if (!Cache::has($openid)) {
            return $this->error('请重新微信授权');
        }

        return $this->success(['token' => null]); // 用户不存在返回null，前端引导绑定手机号
    }

    /**
     * 微信登录，共四步
     * 第四步：微信登录后，注册用户
     * 前端微信登录后发现没有注册过，引导绑定手机号后的注册
     */
    public function wxRegister(Request $request)
    {
        $mobile = $request->input('mobile');
        $code = $request->input('code');
        $openid = $request->input('openid');

        $code_cache = Cache::get("sms:" . $mobile);
        if (!$code_cache && $code != 1234) {
            return $this->error('验证码已过期');
        }

        if ($code != $code_cache && $code != 1234) {
            return $this->error('验证码错误');
        }
        Cache::forget("sms:" . $mobile);

        $data = Cache::pull($openid);
        if (!$data) {
            return $this->error('登录缓存过期，请重新登录');
        }
        $user = User::query()->where('mobile', $mobile)->first();
        if (!$user) {
            $user = User::create([
                'mobile' => $mobile,
                'unionid' => $data['unionid'],
                'name' => $data['nickname'],
                'avatar' => $data['avatar'],
                'openid' => $openid
            ]);
            //新人奖励
            $award = AdminSetting::query()->where('id', 1)->where('status', 1)->first();
            if ($award) {
                $user->amount = (int)$award['value'];

                UserAmountLog::query()->create(
                    [
                        'user_id' => $user->id,
                        'amount' => (int)$award['value'],
                        'balance' => $user->amount,
                        'type' => 0,
                        'map_id' => $award['id'],
                        'remark' => $award['slug'],
                    ]
                );
                $user->save();
            }
        } else {
            $user->openid = $openid;
            $user->save();
        }
        $token = $user->createToken($mobile);
        return $this->success(['token' => $token->plainTextToken]);
    }

    /**
     * 小程序登录
     */
    public function wxLogin(Request $request)
    {
        $unionid = $request->input('unionid');
        $user = User::query()->where('unionid', $unionid)->first();
        $tokenstr = null;
        if ($user) {
            $token = $user->createToken($user->mobile);
            $tokenstr = $token->plainTextToken;
        }
        return $this->success(['user' => $user, 'token' => $tokenstr]);
    }

    /**
     * 小程序注册与绑定用户
     */
    public function wxLoginRegister(Request $request)
    {
        $mobile = $request->input('mobile');
        $unionid = $request->input('unionid');
        $openid = $request->input('openid');

        if (!$mobile || !$unionid) {
            return $this->error('参数错误');
        }

        $user = User::query()->where('mobile', $mobile)->first();
        if (!$user) {
            $user = User::create([
                'mobile' => $mobile,
                'name' => '金橡果用户',
                'miniprogram_openid' => $openid,
                'unionid' => $unionid
            ]);
            $user->name = $user->name . '-' . $user->id;
            // 新人奖励
            $award = AdminSetting::query()->where('id', 1)->where('status', 1)->first();
            if ($award) {
                $user->amount = (int)$award['value'];

                UserAmountLog::query()->create(
                    [
                        'user_id' => $user->id,
                        'amount' => (int)$award['value'],
                        'balance' => $user->amount,
                        'type' => 0,
                        'map_id' => $award['id'],
                        'remark' => $award['slug'],
                    ]
                );
            }
            $user->save();
        } else {
            $user->miniprogram_openid = $openid;//绑定openid
            $user->unionid = $unionid; // 绑定unionid
            $user->save();
        }

        $token = $user->createToken($mobile);
        return $this->success(['token' => $token->plainTextToken]);
    }

    /**
     * 获取小程序分享二维码
     */
    public function getMiniProgramQrcode(Request $request, Response $response)
    {
        $user = $request->user();
        $path = 'miprogramusercode/' . $user->code . '.jpg';
        if (Storage::disk('aliyun')->exists($path))
            return $this->success(trim(config('filesystems.disks.aliyun.domain'), '/') . '/' . $path);

        $app = Factory::miniProgram(config('wechat.mini_program.default'));
        $qrcode_response = $app->app_code->getUnlimit(($user->code), [
            'page' => 'pages/game/game',
            'width' => 150,
            'check_path' => false
        ]);
        if ($qrcode_response instanceof \EasyWeChat\Kernel\Http\StreamResponse) {
            $imageData = $qrcode_response->getBodyContents();
            $result = Storage::disk('aliyun')->put($path, $imageData);
            if ($result) {
                return $this->success(trim(config('filesystems.disks.aliyun.domain'), '/') . '/' . $path);
            } else {
                return $this->error('获取二维码失败');
            }
        } else {
            return $this->error('获取二维码失败');
        }
    }

    /**
     * 获取用户邀请记录
     */
    public function getShareList(Request $request)
    {
        $userId = $request->user()->id;

        $list = UserInvite::query()->where('from_user_id', $userId)->get();
        if ($list) {
            $uids = $list->pluck('user_id')->toArray();
            $users = User::query()->whereIn('id', $uids)->selectRaw("id, name, avatar")->get()->keyBy('id')->toArray();
            $list = $list->toArray();
            foreach ($list as &$item) {
                $item = [
                    'avatar' => $users[$item['user_id']]['avatar'] ?? '',
                    'nickname' => $users[$item['user_id']]['name'] ?? '',
                    'create_time' => $item['created_at'],
                ];
            }
            unset($item);
        }

        return $this->success($list);
    }

    /**
     * 获取用户分享奖励配置
     */
    public function getShareConfig()
    {
        $list = InviteConfig::query()->orderBy('user_count', 'asc')->get()->toArray();
        return $this->success($list);
    }

    public function coinList(Request $request)
    {
        $userId = $request->user()->id;

        $list = UserCoin::query()
            ->leftJoin('coin', 'coin.id', '=', 'user_coin.coin_id')
            ->where('user_coin.user_id', $userId)
            ->where('coin.is_true', Coin::IS_TRUE_YES)
            ->selectRaw('coin.*, user_coin.created_at as date, pay_status, pay_time, apply_status, apply_time')
            ->get();

        $icons = $list->where('type', Coin::TYPE_ZM)
            ->where('apply_status', UserCoin::APPLY_STATUS_NO)
            ->pluck('icon')->toArray();

        $apply = true;

        // 统计需求字母及用户已解锁字母的数量
        $iconCounts = array_count_values($icons);
        $requiredCounts = array_count_values(str_split(Coin::TYPE_ZM_STR));

        // 遍历需求字母，逐一匹配用户已解锁的字母
        foreach ($requiredCounts as $char => $count) {
            if (!isset($iconCounts[$char]) || $iconCounts[$char] < $count) {
                $apply = false;
                break;
            }
        }

        $list = $list->toArray();
        foreach ($list as &$item) {
            if ($item['type'] == Coin::TYPE_LW) {
                $item['icon'] = trim(config('filesystems.disks.aliyun.domain'), '/') . '/' . $item['icon'];
            } else if ($item['type'] == Coin::TYPE_ZM) {
                if (($item['apply_status'] == UserCoin::APPLY_STATUS_NO && !$apply) || !in_array($item['icon'], Coin::TYPE_ZM_SET)) {
                    $item['apply_status'] = UserCoin::APPLY_STATUS_OFF;
                }
            }
        }
        unset($item);
        return $this->success($list);
    }

    public function coinSave(Request $request)
    {
        $userId = $request->user()->id;
        $coinId = $request->input('coin_id');
        $content = $request->input('content', '');
        if (!$coinId) {
            return $this->error('参数错误');
        }
        $coin = Coin::query()->find($coinId);
        if (!$coin) {
            return $this->error('硬币不存在');
        }

        if ($coin->is_new_user_only == Coin::IS_NEW_USER_ONLY_YES && strtotime($request->user()->created_at) < (time() - User::NEW_USER_TIME)) {
            return $this->error('新用户专享，您无法领取');
        }

        // if ($coin->type == Coin::TYPE_JIN) {
        //     return $this->error('不支持解锁该硬币');
        // }

        if ($coin->is_unlock == Coin::IS_UNLOCK_YES) {
            return $this->error('硬币已被领取');
        }

        try {
            DB::beginTransaction();
            UserCoin::query()->create([
                'user_id' => $userId,
                'coin_id' => $coinId,
                'content' => $content
            ]);
            $coin->is_unlock = Coin::IS_UNLOCK_YES;
            $coin->save();

            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error(__METHOD__, $e->getTrace());
        }

        return $this->success($coin->toArray());
    }

    public function coinPay(Request $request)
    {
        $userId = $request->user()->id;
        $coinId = $request->input('coin_id');
        if (!$coinId) {
            return $this->error('参数错误');
        }
        $coin = Coin::query()->find($coinId);
        if (!$coin) {
            return $this->error('硬币不存在');
        }

        $userCoin = UserCoin::query()->where('user_id', $userId)->where('coin_id', $coinId)->first();
        if (!$userCoin) {
            return $this->error('未获得该硬币');
        }

        if ($coin->type == Coin::TYPE_ZM) {
            $ids = UserCoin::query()
                ->leftJoin('coin', 'coin.id', '=', 'user_coin.coin_id')
                ->where('user_coin.user_id', $userId)
                ->where('coin.type', Coin::TYPE_ZM)
                ->where('coin.apply_status', UserCoin::APPLY_STATUS_NO)
                ->selectRaw('coin.icon, user_coin.id, user_coin.coin_id')
                ->get();
            $icons = $ids->pluck('icon')->toArray();
            $requiredIcons = str_split(Coin::TYPE_ZM_STR);

            // 统计需求字母及用户已解锁字母的数量
            $iconCounts = array_count_values($icons);
            $requiredCounts = array_count_values($requiredIcons);

            $updateIds = [];

            // 优先匹配当前 $coinId 对应的 UserCoin
            $currentCoin = $ids->where('coin_id', $coinId)->first();
            $updateIds[] = $currentCoin->id;
            $requiredCounts[$currentCoin->icon]--;
            $iconCounts[$currentCoin->icon]--;

            // 遍历需求字母，逐一匹配用户已解锁的字母
            foreach ($requiredCounts as $char => $count) {
                if (!isset($iconCounts[$char]) || $iconCounts[$char] < $count) {
                    // 如果用户没有解锁该字母或者单个字母不够目标数量，返回错误
                    return $this->error('请先解锁其他字母');
                }

                // 获取需要更新的记录ID
                $updateIds = array_merge(
                    $updateIds,
                    $ids->where('icon', $char)->take($count)->pluck('id')->toArray()
                );
            }

            // 更新满足条件的记录
            UserCoin::query()->whereIn('id', $updateIds)->update([
                'parent_coin_id' => $coinId,
                'apply_status' => UserCoin::APPLY_STATUS_YES,
                'apply_time' => date('Y-m-d H:i:s')
            ]);
        } else {
            $userCoin->apply_status = UserCoin::APPLY_STATUS_YES;
            $userCoin->apply_time = date('Y-m-d H:i:s');
            $userCoin->save();
        }

        return $this->success();
    }

    public function goldCoinSave(Request $request)
    {
        $userId = $request->user()->id;

        // $log = UserCoinLog::query()->where('user_id', $userId)->count();
        $user = User::query()->find($userId);
        $goldPrice = AdminSetting::query()->where('id', '2')->first();
        $price = 500; // 默认
        if ($goldPrice) {
            $price = intval($goldPrice['value']);
        }
        if ($user->amount < $price) {
            return $this->error('余额不足');
        }

        //用户已经解锁金币
        $coinIds = UserCoin::query()->where('user_id', $userId)->get()->pluck('coin_id')->toArray();
        $coins = Coin::query()
            ->where('type', Coin::TYPE_JIN)
            ->where('status', Coin::STATUS_OPEN)
            ->where('is_true', Coin::IS_TRUE_NO)
            ->where(function ($query) use ($coinIds) {
                if ($coinIds) {
                    $query->whereNotIn('id', $coinIds);
                }
            })->get();
        $coinUnlock = $coins->random();
        if (!$coinUnlock) {
            return $this->error('假金币已全部解锁');
        }

        UserCoin::query()->create([
            'user_id' => $userId,
            'coin_id' => $coinUnlock->id,
        ]);
        $log = UserCoinLog::query()->create([
            'user_id' => $userId,
            'coin_ids' => json_encode([$coinUnlock->id]),
            'amount' => $price,
        ]);
        $user->amount = bcsub($user->amount, $price);
        $user->save();

        UserAmountLog::query()->create(
            [
                'user_id' => $userId,
                'amount' => -$price,
                'balance' => $user->amount,
                'type' => 0,
                'map_id' => $log->id,
                'remark' => '解锁金币',
            ]
        );

        return $this->success(['count' => 1, 'is_false' => $coins->count() > 1]);
    }

    public function coinClueSave(Request $request)
    {
        $userId = $request->user()->id;
        $id = $request->input('id');
        if (!$id) {
            return $this->error('参数错误');
        }
        $coinClue = CoinClue::query()->find($id);
        if (!$coinClue) {
            return $this->error('踪迹线索不存在');
        }

        $coin = Coin::query()->find($coinClue->coin_id);
        if ($coin->is_new_user_only == Coin::IS_NEW_USER_ONLY_YES && strtotime($request->user()->created_at) < (time() - User::NEW_USER_TIME)) {
            return $this->error('新用户专享，您无法解锁');
        }


        $user = User::query()->find($userId);
        if ($user->amount < $coinClue->amount) {
            return $this->error('余额不足');
        }

        $userCoinClueData = [
            'user_id' => $userId,
            'coin_id' => $coinClue->coin_id,
            'coin_clue_id' => $coinClue->id,
            'amount' => $coinClue->amount
        ];
        if ($coinClue->is_circle === CoinClue::IS_CIRCLE_YES) {
            $coinClueList = CoinClue::query()->where([
                'is_circle' => CoinClue::IS_CIRCLE_YES,
                'coin_id' => $coinClue->coin_id
            ])->get();
            $clueCount = $coinClueList->count();
            $coinClueIds = $coinClueList->pluck('id')->toArray();

            $userCoinClue = UserCoinClue::query()->where([
                'user_id' => $userId,
                'coin_id' => $coinClue->coin_id,
                'status' => UserCoinClue::STATUS_DONE,
            ])->whereIn('coin_clue_id', $coinClueIds)->orderBy('created_at', 'desc')->get();

            $coin = Coin::query()->find($coinClue->coin_id);
            $initialRadius = $coin->type == Coin::TYPE_YIN ? self::RADIUS_SILVER : self::RADIUS_COPPER;
            $shrinkStep = bcdiv($initialRadius, $clueCount); // 获取步进，每次固定缩小的半径（单位：米）
            $userClueCount = $userCoinClue->count() + 1;
            $userClueCount = min($userClueCount, $clueCount);
            if ($userClueCount == $clueCount) {
                $userCoinClueData['longitude'] = $coin->longitude;
                $userCoinClueData['latitude'] = $coin->latitude;
                $userCoinClueData['radius'] = 0;
            } else {
                if ($userClueCount === 1) {
                    $lat = $coin->false_latitude;
                    $lng = $coin->false_longitude;
                    $curRadius = $initialRadius;
                } else {
                    $lat = $userCoinClue[0]->latitude;
                    $lng = $userCoinClue[0]->longitude;
                    $curRadius = $userCoinClue[0]->radius;
                }
                $newRadius = max(0, ($curRadius - $shrinkStep)); // 保证最小0
                $newCenter = $this->generateNextCircleCenterWithConstraints(
                    $lat,
                    $lng,
                    $curRadius,
                    $newRadius,
                    ['lat' => $coin->latitude, 'lng' => $coin->longitude]
                );
                $userCoinClueData['longitude'] = $newCenter['lng'];
                $userCoinClueData['latitude'] = $newCenter['lat'];
                $userCoinClueData['radius'] = $newRadius;
            }
        }

        try {
            DB::beginTransaction();
            $clueLog = UserCoinClue::query()->create($userCoinClueData);
            $user->amount = $user->amount - $coinClue->amount;
            $user->save();

            UserAmountLog::query()->create(
                [
                    'user_id' => $userId,
                    'amount' => -$coinClue->amount,
                    'balance' => $user->amount,
                    'type' => 0,
                    'map_id' => $clueLog->id,
                    'remark' => '解锁线索',
                ]
            );

            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error(__METHOD__, $e->getTrace());
        }

        return $this->success($coinClue->toArray());
    }

    public function upload(Request $request)
    {
        $result = Storage::disk('aliyun')->putFile('files', $request->file('file'));
        return $this->success([trim(config('filesystems.disks.aliyun.domain'), '/') . '/' . $result]);
    }

    public function code(Request $request)
    {
        $user = User::query()->find($request->user()->id);
        if (!$user->code) {
            $user->code = $this->genCode();
            $user->save();
        }
        $number = UserInvite::query()->where('from_user_id', $user->id)->count();

        return $this->success(['code' => $user->code, 'number' => $number]);
    }

    public function codeSave(Request $request)
    {
        $code = $request->input('code', '');
        if (!$code) {
            return $this->error('参数错误');
        }
        $user = User::query()->where('code', $code)->first();
        if (!$user || $user->id == $request->user()->id) {
            return $this->error('邀请码错误');
        }
        $log = UserInvite::query()->where('user_id', $request->user()->id)->first();
        if ($log) {
            return $this->error('已经被邀请过，无法重复参加');
        }

        $from_user_count = UserInvite::query()->where('from_user_id', $user->id)->count();
        $config = InviteConfig::query()->where('user_count', $from_user_count + 1)->orderBy('updated_at', 'desc')->first();

        $invite = UserInvite::query()->create([
            'from_user_id' => $user->id,
            'user_id' => $request->user()->id,
            'reward' => (int)($config ? $config->reward : 0),
        ]);
        $user->amount = $user->amount + (int)($config ? $config->reward : 0);
        $user->save();

        UserAmountLog::query()->create(
            [
                'user_id' => $user->id,
                'amount' => (int)($config ? $config->reward : 0),
                'balance' => $user->amount,
                'type' => 0,
                'map_id' => $invite->id,
                'remark' => '邀请好友',
            ]
        );

        $clue_id = $request->input('clue_id', '');
        if ($clue_id) {
            $clue = CoinClue::find($clue_id);
            if (!$clue) {
                return $this->error('线索不存在');
            }

            $userClue = UserCoinClue::query()->firstOrNew([
                'coin_id' => $clue->coin_id,
                'coin_clue_id' => $clue_id,
                'user_id' => $user->id,
            ]);

            $userClue->number = ($userClue->exists ? $userClue->number : 0) + 1;
            $userClue->status = $userClue->number < $clue->number ? UserCoinClue::STATUS_NO_DONE : UserCoinClue::STATUS_DONE;
            $userClue->save();

            if ($clue->is_circle === CoinClue::IS_CIRCLE_YES && $userClue->number == $clue->number) {
                $coinClueList = CoinClue::query()->where([
                    'is_circle' => CoinClue::IS_CIRCLE_YES,
                    'coin_id' => $clue->coin_id
                ])->get();
                $clueCount = $coinClueList->count();
                $coinClueIds = $coinClueList->pluck('id')->toArray();

                $userCoinClue = UserCoinClue::query()->where([
                    'user_id' => $user->id,
                    'coin_id' => $clue->coin_id,
                    'status' => UserCoinClue::STATUS_DONE,
                ])->whereIn('coin_clue_id', $coinClueIds)->orderBy('created_at', 'desc')->get();

                $coin = Coin::query()->find($clue->coin_id);
                $initialRadius = $coin->type == Coin::TYPE_YIN ? self::RADIUS_SILVER : self::RADIUS_COPPER;
                $shrinkStep = bcdiv($initialRadius, $clueCount); // 获取步进，每次固定缩小的半径（单位：米）
                $userClueCount = $userCoinClue->count() + 1;
                $userClueCount = min($userClueCount, $clueCount);
                if ($userClueCount == $clueCount) {
                    $userCoinClueData['longitude'] = $coin->longitude;
                    $userCoinClueData['latitude'] = $coin->latitude;
                    $userCoinClueData['radius'] = 0;
                } else {
                    if ($userClueCount === 1) {
                        $lat = $coin->false_latitude;
                        $lng = $coin->false_longitude;
                        $curRadius = $initialRadius;
                    } else {
                        $lat = $userCoinClue[0]->latitude;
                        $lng = $userCoinClue[0]->longitude;
                        $curRadius = $userCoinClue[0]->radius;
                    }
                    $newRadius = max(0, ($curRadius - $shrinkStep)); // 保证最小0
                    $newCenter = $this->generateNextCircleCenterWithConstraints(
                        $lat,
                        $lng,
                        $curRadius,
                        $newRadius,
                        ['lat' => $coin->latitude, 'lng' => $coin->longitude]
                    );
                    $userCoinClueData['longitude'] = $newCenter['lng'];
                    $userCoinClueData['latitude'] = $newCenter['lat'];
                    $userCoinClueData['radius'] = $newRadius;
                }
                $userClue->update($userCoinClueData);
            }
        }


        return $this->success();
    }

    private function genCode()
    {
        $chars = str_shuffle("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
        $res = "";

        while (true) {
            for ($i = 0; $i < 6; $i++) {
                $res .= $chars[mt_rand(0, strlen($chars) - 1)];
            }
            $user = User::query()->where('code', $res)->count();
            if (!$user) {
                break;
            }
        }

        return $res;
    }

    /**
     * 保存用户昵称
     */
    public function saveNickname(Request $request)
    {
        $nickname = $request->input('nickname');
        if (!$nickname) return $this->error('参数错误');

        $user = $request->user();

        if ($nickname === $user->name) return $this->error('无需修改');

        $key = $user->id . '_editName';
        if (Cache::has($key)) {
            return $this->error('三天内不可多次修改');
        }
        Cache::put($key, true, 259200); // 三天内不可重复修改

        $user->name = $nickname;
        $user->save();

        return $this->success([], '昵称修改成功');
    }

    /**
     * 小程序更新头像
     */
    public function saveAvatar(Request $request)
    {
        $user = $request->user();
        $user->avatar = $request->input('avatar'); // 绑定unionid
        $user->save();
        return $this->success();
    }
}
